package com.cch.cooperation.biz.common.valid.util;

import com.cch.cooperation.biz.common.util.SpringUtil;
import com.cch.cooperation.common.exception.BizException;
import org.springframework.context.ApplicationContext;

import javax.validation.Valid;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 * Service 层校验工具类
 *
 * @author cch on 2020/11/06
 **/
public class ServiceValidUtil {

    private final static String VALID_PACKAGE = "com.cch.cooperation";
    private volatile static HashMap<String, List<Integer>> validMap;    // 需要校验的方法表，key：方法名，value：方法参数下标

    public static void validServiceFun(String functionName, Object[] objects) throws BizException {
        if(needValid(functionName)) {
            for (Integer idx : validMap.get(functionName)) {
                Object obj = objects[idx];
                ValidUtil.valid(obj);
            }
        }
    }

    private static boolean needValid(String functionName) {
        if (validMap == null) {
            synchronized (ServiceValidUtil.class) {
                if (validMap == null) {
                    initValidMap();
                }
            }
        }
        return validMap.containsKey(functionName);
    }

    private static void initValidMap() {
        validMap = new HashMap<>();
        ApplicationContext applicationContext = SpringUtil.getApplicationContext();
        String[] beanNames = applicationContext.getBeanDefinitionNames();
        for (String beanName : beanNames) {
            Object obj = applicationContext.getBean(beanName);
            if (obj.getClass().getName().startsWith(VALID_PACKAGE)) {
                Class c = obj.getClass().getSuperclass();
                Method[] methods = c.getMethods();
                for (Method method : methods) {
                    Annotation[][] annotations = method.getParameterAnnotations();
                    for (int i = 0; i < annotations.length; i++) {
                        for (Annotation annotation : annotations[i]) {
                            if (annotation.annotationType() == Valid.class) {
                                String key = c.getName() + "." + method.getName();
                                if(!validMap.containsKey(key)) {
                                    validMap.put(key, new ArrayList<>());
                                }
                                validMap.get(key).add(i);
                            }
                        }
                    }
                }
            }
        }
    }
}
